home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / aztecnos.arc / ALLOC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-22  |  6.6 KB  |  298 lines

  1. #include <stdio.h>
  2. #include "alloc.h"
  3. #include "proc.h"
  4. /* memory allocation routines
  5.  *
  6.  * Adapted from alloc routine in K&R; memory statistics and interrupt
  7.  * protection added for use with net package. Must be used in place of
  8.  * standard Turbo-C library routines because the latter check for stack/heap
  9.  * collisions. This causes erroneous failures because process stacks are
  10.  * allocated off the heap.
  11.  */
  12.  
  13. HEADER *morecore();
  14. char *sbrk();
  15. void free();
  16.  
  17. static HEADER base, *allocp = NULLHDR;
  18. static unsigned memfail;
  19. static unsigned allocs;
  20. static char *heapbase;
  21. static char *heaptop;
  22. static unsigned heapsize;
  23.  
  24. /* Define ALLOCDEBUG for allocation recording. Note: works only with
  25.  * small memory model
  26.  */
  27. #ifdef    ALLOCDEBUG
  28. #define    NALLOC    150
  29. /* Map of allocated memory chunks */
  30. struct alloc {
  31.     void *addr;
  32.     unsigned size;
  33.     long pc;
  34. };
  35. struct alloc alloc[NALLOC];
  36. #endif
  37.  
  38. /* Allocate block of 'nb' bytes */
  39. void *
  40. malloc(nb)
  41. unsigned nb;
  42. {
  43.     register HEADER *p, *q;
  44.     register unsigned nu;
  45.     char i_state;
  46.  
  47. #ifdef    ALLOCDEBUG
  48.     struct alloc *ap;
  49.     unsigned short *ptr;
  50. #endif
  51.  
  52.     if(nb == 0)
  53.         return NULL;
  54.     i_state = dirps();
  55.     /* Round up to full block, then add one for header */
  56.     nu = ((nb + ABLKSIZE - 1) / ABLKSIZE) + 1;
  57.     if ((q = allocp) == NULLHDR){
  58.         base.s.ptr = allocp = q = &base;
  59.         base.s.size = 1;
  60.     }
  61.     for (p = q->s.ptr; ; q = p, p = p->s.ptr){
  62.         if (p->s.size >= nu){
  63.             /* This chunk is at least as large as we need */
  64.             if (p->s.size == nu){
  65.                 /* Perfect fit; remove from list */
  66.                 q->s.ptr = p->s.ptr;
  67.             } else {
  68.                 /* Carve out piece from end of entry */
  69.                 p->s.size -= nu;
  70.                 p += p->s.size;
  71.                 p->s.size = nu;
  72.             }
  73.             allocp = q;
  74.             p->s.ptr = p;    /* for auditing */
  75. #ifdef    ALLOCDEBUG
  76.             for(ap = alloc;ap < &alloc[NALLOC];ap++){
  77.                 if(ap->addr == NULL){
  78.                     ap->addr = (void *)(p+1);
  79.                     ap->size = nb;
  80.                     ptr = &nb;
  81. #ifdef    LARGECODE
  82.                     ap->pc = (long)ptr[-1] << 16 +
  83.                         (long)ptr[-2];
  84. #else
  85.                     ap->pc = (long)ptr[-1];
  86. #endif
  87.                     break;
  88.                 }
  89.             }
  90. #endif
  91.             restore(i_state);
  92.             allocs++;
  93.             return (void *)(p + 1);
  94.         }
  95.         if (p == allocp && (p = morecore(nu)) == NULLHDR){
  96.             memfail++;
  97.             restore(i_state);
  98.             return NULL;
  99.         }
  100.     }
  101. }
  102. /* Get more memory from the system and put it on the heap */
  103. HEADER *
  104. morecore(nu)
  105. unsigned nu;
  106. {
  107.     register char *cp;
  108.     register HEADER *up;
  109.  
  110.     /* Before calling main, the Turbo startup routines call malloc to
  111.      * save the environment. In turn this calls morecore, all before we
  112.      * get a chance to call grabcore. Hence the null test for heaptop.
  113.      */
  114.     if(heaptop != NULL && sbrk(0) >= heaptop)
  115.         return NULLHDR;    /* Don't let it overwrite stack */
  116.     if ((int)(cp = sbrk(nu * ABLKSIZE)) == -1)
  117.         return NULLHDR;
  118.     up = (HEADER *)cp;
  119.     up->s.size = nu;
  120.     up->s.ptr = up;    /* satisfy audit */
  121.     free((void *)(up + 1));
  122.     return allocp;
  123. }
  124. /* Grab as much memory as possible from the system and put it on the heap */
  125. unsigned
  126. grabcore(stktop)
  127. char *stktop;    /* Beginning of stack region */
  128. {
  129.     register HEADER *up;
  130.  
  131.     /* Find out where the break is */
  132.     heapbase = sbrk(0);
  133.     /* Now try to push it as high as possible */
  134.     while(brk(stktop) == -1)
  135.         stktop -= 16;
  136.  
  137.     heapsize = stktop - heapbase;
  138.     heaptop = sbrk(0);
  139.     /* Initialize the heap pointers */
  140.     if (allocp == NULLHDR){
  141.         base.s.ptr = allocp = &base;
  142.         base.s.size = 1;
  143.     }
  144.     up = (HEADER *)heapbase;
  145.     up->s.size = heapsize / sizeof(HEADER);
  146.     up->s.ptr = up;    /* satisfy audit */
  147.     free((void *)(up + 1));
  148.     return heapsize;
  149. }
  150.  
  151. /* Put memory block back on heap */
  152. void
  153. free(blk)
  154. void *blk;
  155. {
  156.     register HEADER *p, *q;
  157.     unsigned short *ptr;
  158.     char i_state;
  159. #ifdef    ALLOCDEBUG
  160.     struct alloc *ap;
  161. #endif
  162.  
  163.     if(blk == NULL)
  164.         return;
  165.     i_state = dirps();
  166. #ifdef    ALLOCDEBUG
  167.     for(ap = alloc;ap < &alloc[NALLOC];ap++){
  168.         if(ap->addr == blk){
  169.             ap->addr = NULL;
  170.             break;
  171.         }
  172.     }
  173. #endif
  174.     p = (HEADER *)blk - 1;
  175.     /* Audit check */
  176.     if(p->s.ptr != p){
  177.         ptr = (unsigned short *)&blk;
  178.         printf("WARNING!! freeing garbage (0x%x) pc = 0x%x %x proc %s\n",blk,
  179.             ptr[-1],ptr[-2],Curproc->name);
  180.         ps();
  181.         restore(i_state);
  182. #ifdef    Z80
  183.         printf("SP = 0x%x\n",getsp());
  184.         for(;;) ;
  185. #else
  186.         return;
  187. #endif
  188.     }
  189.     /* Search the free list looking for the right place to insert */
  190.     for(q = allocp; !(p > q && p < q->s.ptr); q = q->s.ptr){
  191.         /* Highest address on circular list? */
  192.         if(q >= q->s.ptr && (p > q || p < q->s.ptr))
  193.             break;
  194.     }
  195.     if(p + p->s.size == q->s.ptr){
  196.         /* Combine with front of this entry */
  197.         p->s.size += q->s.ptr->s.size;
  198.         p->s.ptr = q->s.ptr->s.ptr;
  199.     } else {
  200.         /* Link to front of this entry */
  201.         p->s.ptr = q->s.ptr;
  202.     }
  203.     if(q + q->s.size == p){
  204.         /* Combine with end of this entry */
  205.         q->s.size += p->s.size;
  206.         q->s.ptr = p->s.ptr;
  207.     } else {
  208.         /* Link to end of this entry */
  209.         q->s.ptr = p;
  210.     }
  211.     allocp = q;
  212.     restore(i_state);
  213.     allocs--;
  214. }
  215.  
  216. #ifdef    notdef
  217. /* Move existing block to new area */
  218. void *
  219. realloc(area,size)
  220. void *area;
  221. unsigned size;
  222. {
  223.     unsigned osize;
  224.     HEADER *hp;
  225.     char *cp;
  226.     char i_state;
  227.  
  228.     hp = ((HEADER *)area) - 1;
  229.     osize = (hp->s.size -1) * ABLKSIZE;
  230.  
  231.     /* Make sure nobody else comes in and takes it */
  232.     i_state = dirps();
  233.     free(area);
  234.     if((cp = malloc(size)) != NULL && cp != area)
  235.         memcpy((char *)cp,(char *)area,size>osize? osize : size);
  236.     restore(i_state);
  237.     return cp;
  238. }
  239. #endif
  240. /* Allocate block of cleared memory */
  241. void *
  242. calloc(nelem,size)
  243. unsigned nelem;    /* Number of elements */
  244. unsigned size;    /* Size of each element */
  245. {
  246.     register unsigned i;
  247.     register char *cp;
  248. #ifdef    ALLOCDEBUG
  249.     struct alloc *ap;
  250.     short *ptr;
  251. #endif
  252.     i = nelem * size;
  253.     if((cp = malloc(i)) != NULL)
  254.         memset(cp,0,i);
  255. #ifdef    ALLOCDEBUG
  256.     if(cp == NULL)
  257.         return cp;
  258.     /* Adjust caller field to indicate real caller, not calloc() */
  259.     ptr = (short *)&nelem;
  260.     for(ap = alloc; ap < &alloc[NALLOC];ap++)
  261.         if(ap->addr == cp)
  262.             ap->pc = (long)ptr[-1];
  263. #endif
  264.     return cp;
  265. }
  266. /* Print free list map */
  267. memstat()
  268. {
  269.     HEADER *p;
  270.     unsigned total;
  271.  
  272.     total = 0;
  273.     p = &base;
  274.     do {
  275.         total += p->s.size * sizeof(HEADER);
  276.         printf("0x%lx %u",ptol(p),p->s.size * ABLKSIZE);
  277.         if(p == allocp)
  278.             printf(" <-- allocp\n");
  279.         else
  280.             printf("\n");
  281.         p = p->s.ptr;
  282.     } while(p != &base);
  283.     printf("Heap base %lx size %u; allocs %u fails %u free %u bytes (%lu%%)\n",
  284.         ptol(heapbase),heapsize,allocs,memfail,total,
  285.         100L*total/heapsize);
  286. #ifdef    ALLOCDEBUG
  287.     {
  288.         struct alloc *ap;
  289.         printf("addr      size      caller\n");
  290.         for(ap = alloc;ap < &alloc[NALLOC];ap++){
  291.             if(ap->addr != NULL)
  292.                 printf("0x%-8x%-10d%-10lx\n",ap->addr,
  293.                     ap->size,ap->pc);
  294.         }
  295.     }
  296. #endif
  297. }
  298.